// 模板替换类，Time和Weather类都使用的方法
class replaceTemplate {
    rptpl(tpl, data) {
        let result = tpl;
        for (const key in data) {
            if (Object.hasOwnProperty.call(data, key)) {
                const value = data[key];
                result = result.replace(`{{ ${key} }}`, value);
            }
        }
        return result;
    }
}

class Time extends replaceTemplate {

    // 热门国家时区列表
    area = [
        { name: "China", country: "中国", capital: "北京", timezone: 8 },
        { name: "America", country: "美国", capital: "华盛顿", timezone: -5 },
        { name: "England", country: "英国", capital: "伦敦", timezone: 0 },
        { name: "France", country: "法国", capital: "巴黎", timezone: 1 },
        { name: "Thailand", country: "泰国", capital: "曼谷", timezone: 7 },
        { name: "Japan", country: "日本", capital: "东京", timezone: 9 },
        { name: "Brazil", country: "巴西", capital: "巴西利亚", timezone: -3 },
        { name: "Egypt", country: "埃及", capital: "开罗", timezone: 2 },
        { name: "Russia", country: "俄罗斯", capital: "莫斯科", timezone: 3 },
        { name: "Australia", country: "澳大利亚", capital: "堪培拉", timezone: 10 }
    ];

    // 默认时间选项配置
    timeOption = { country: "中国", capital: "北京", timezone: 8, type: 24 };

    UTCTimeData = {};
    timeData = {};
    bjtimeData = {};

    optionTpl = `<option value="{{ name }}" data-capital="{{ capital }}" data-timezone="{{ timezone }}">{{ country }}</option>`;
    mainTpl = `
        <div class="timebox">
            <span class="small abbr">{{ abbr }}</span>
            <span class="hour">{{ hour }}</span>
            <span>:</span>
            <span class="minute">{{ minute }}</span>
            <span class="second small">{{ second }}</span>
        </div>
        <div class="datebox">
            <span class="week">星期{{ week }}</span>
            <span class="date">{{ year }}年{{ month }}月{{ date }}日</span>
        </div>`;
    bottomTpl = `
        <span class="compare">{{ compare }}</span>
        <span>北京时间</span>
        <span class="bjtime">{{ hour }}:{{ minute }}:{{ second }}</span>
        <span class="bjdate">星期{{ week }}，{{ month }}月{{ date }}日</span>`;

    constructor(doms) {
        super();
        this.doms = doms;
    }

    init() {
        this.renderTime();
        this.renderSelect();
        this.handleEventListener();
        const self = this;
        setInterval(() => {
            self.renderTime();
        }, 200)
    }

    // 渲染select下拉框
    renderSelect() {
        let selectinnerHTML = '';
        for (let i = 0; i < this.area.length; i++) {
            selectinnerHTML += this.rptpl(this.optionTpl, this.area[i]);
        }
        this.doms.oSelect.innerHTML = selectinnerHTML;
    }

    // 添加事件监听,修改时区和显示时间格式
    handleEventListener() {
        this.doms.oCheckbox.addEventListener("click", () => {
            let type = this.doms.oCheckbox.checked ? 12 : 24;
            this.timeOption.type = type;
        })
        this.doms.oSelect.addEventListener("click", () => {
            const index = this.doms.oSelect.selectedIndex;
            let country = this.doms.oSelect.options[index].text;
            if (country != this.timeOption.country) {
                this.timeOption.country = country;
                this.timeOption.capital = this.doms.oSelect.options[index].getAttribute("data-capital");
                this.timeOption.timezone = parseInt(this.doms.oSelect.options[index].getAttribute("data-timezone"));
            }
        })
    }

    // 获取世界时
    getTimeData() {
        const time = new Date();
        this.UTCTimeData.year = time.getUTCFullYear();
        this.UTCTimeData.month = time.getUTCMonth() + 1;
        this.UTCTimeData.date = time.getUTCDate();
        this.UTCTimeData.week = time.getUTCDay();
        this.UTCTimeData.hour = time.getUTCHours();
        this.UTCTimeData.minute = time.getUTCMinutes();
        this.UTCTimeData.second = time.getUTCSeconds();
        this.handleTimeData();
    }

    // 结合配置处理时间为指定格式
    handleTimeData() {

        function handle(timezone, UTCTimeData, type) {
            let data = { ...UTCTimeData };

            const diff = timezone - 8;
            data.compare = `比北京${diff > 0 ? "快" : "慢"}${Math.abs(diff)}小时`;

            data.hour += timezone;
            if (data.hour >= 24 || data < 0) {
                let time;
                if (data.hour >= 24) {
                    data.hour -= 24;
                    time = new Date(new Date().getTime() + 86400000);
                } else {
                    data.hour += 24;
                    time = new Date(new Date().getTime() - 86400000);
                }
                data.year = time.getUTCFullYear();
                data.month = time.getUTCMonth() + 1;
                data.date = time.getUTCDate();
                data.week = time.getUTCDay();
            }

            data.week = ["一", "二", "三", "四", "五", "六", "日"][data.week];

            data.abbr = data.hour > 12 ? "PM" : "AM";
            if (type == 12 && data.hour > 12) {
                data.hour -= 12;
            }

            data.second = data.second < 10 ? "0" + data.second : data.second;
            data.minute = data.minute < 10 ? "0" + data.minute : data.minute;
            data.hour = data.hour < 10 ? "0" + data.hour : data.hour;

            return data

        }

        // 主体时间数据
        this.timeData = handle(this.timeOption.timezone, this.UTCTimeData, this.timeOption.type);

        // 北京时间相关数据，用于对比时使用
        this.bjtimeData = handle(8, this.UTCTimeData, 24);
        this.bjtimeData.compare = this.timeData.compare;
    }


    // 将时间数据渲染到页面
    renderTime() {

        this.getTimeData();

        // 设置标题
        this.doms.oTitle.innerHTML = `${this.timeOption.country}首都${this.timeOption.capital}时间`

        // 主体时间
        this.doms.oMain.innerHTML = this.rptpl(this.mainTpl, this.timeData);

        // 设置页面中与北京时间部分部分是否显示
        if (this.timeOption.country == "中国") {
            this.doms.oBottom.style.display = "none"
        } else {
            this.doms.oBottom.style.display = "block"
            this.doms.oBottom.innerHTML = this.rptpl(this.bottomTpl, this.bjtimeData);
        }

        // 设置am pm缩写是否显示
        if (this.timeOption.type == "12") {
            this.doms.oMain.className = "main abbr";
        } else {
            this.doms.oMain.className = "main";
        }
    }



}

class Weather extends replaceTemplate {

    // 高德天气api接口
    api = `https://restapi.amap.com/v3/weather/weatherInfo?extensions=base&key=dcf50e005d6ff0ce5552de60d470928e&city=`;

    // html模板
    liTpl = `
        <li>
            <span class="city">{{ city }}</span>
            <i class="iconfont {{ icon }}"></i>
            <span class="status">{{ status }}</span>
            <span class="temp">{{ temp }}</span>
        </li>`;

    innerHTML = '';
    count = 0;

    constructor(el, adcodes) {
        super();
        this.el = el;
        this.adcodes = adcodes ? adcodes : [440105, 320114, 210211, 340104, 411524];
    }

    init() {
        for (let i = 0; i < this.adcodes.length; i++) {
            this.getWeatherData(this.adcodes[i]);
        }
    }

    // 发送请求获取天气数据并行处理
    getWeatherData(adcode) {
        if (this.count == 5) return;
        Weather.gatAjax(this.api + adcode)
            .then(res => {
                const rawdata = JSON.parse(res);
                if (rawdata.status == "1") {
                    const data = this.handleWeatherData(rawdata.lives[0]);
                    this.replaceTemplate(data);
                    if (this.count == 5) this.renderDom();
                }
            })
    }
    // 处理获取的数据转化为指定格式
    handleWeatherData(data) {
        let { city, weather: status, temperature: temp } = data;
        temp += "℃";
        const result = { city, status, temp };
        result.icon = Weather.getIconClass(status);
        return result;
    }
    // 根据处理后数据替换模板
    replaceTemplate(data) {
        let liDomStr = this.rptpl(this.liTpl, data)
        this.innerHTML += liDomStr;
        this.count += 1;
    }
    // 将liDOM字符串渲染至ul中
    renderDom() {
        this.el.innerHTML = this.innerHTML;
    }


    static getIconClass(status) {
        let icon = '';
        switch (true) {
            case status.indexOf("霾") != -1:
                icon = 'icon-wumai';
                break;
            case status.indexOf("雪") != -1:
                icon = 'icon-xue2';
                break;
            case status.indexOf("雾") != -1:
                icon = 'icon-wu';
                break;
            case status.indexOf("云") != -1:
                icon = 'icon-duoyun2';
                break;
            case status.indexOf("小雨") != -1:
                icon = 'icon-xiaoyu1';
                break;
            case status.indexOf("中雨") != -1:
                icon = 'icon-zhongyu';
                break;
            case status.indexOf("大雨") != -1:
                icon = 'icon-dayu2';
                break;
            case status == "阴":
                icon = 'icon-yin';
                break;
            case status == "晴":
                icon = 'icon-qing2';
                break;
            default:
                icon = 'icon-weizhitianqi'
        }
        return icon;
    }

    // 封装xhr
    static gatAjax(url) {
        return new Promise((resolve, reject) => {
            var xhr = new XMLHttpRequest();
            xhr.onreadystatechange = function () {
                if (xhr.readyState === 4) {
                    if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
                        resolve(xhr.responseText);
                    } else {
                        reject(xhr.status);
                    }
                }
            };
            xhr.open("GET", url, true);
            xhr.send();
        });
    }

}

const oUl = document.querySelector(".weather ul");
const adcodes = [440105, 320114, 210211, 340104, 411524];
new Weather(oUl, adcodes).init();

const oSelect = document.querySelector("select[name='area']");
const oCheckbox = document.getElementById("mode-switch");
const oTitle = document.querySelector(".top span.title");
const oMain = document.querySelector(".main");
const oBottom = document.querySelector(".bottom");
new Time({ oSelect, oCheckbox, oTitle, oMain, oBottom }).init();